﻿local RosterDirty = 0
local StatusDirty = 0
local _CurrentTime = 0

local function print(text)
	DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF"..text);
end

function OZ_EventRoster()
	RosterDirty = GetTime()
	StatusDirty = RosterDirty
end

function OZ_EventStatus()
	StatusDirty = GetTime()
end

function OZ_EventTarget()
	StatusDirty = GetTime()
end

function OZ_readyCheck()
    local m = OZ_RaidRoster.nMembers
    for i = 1,m do
        local player = OZ_RaidRoster.member[i]
        local rc = GetReadyCheckStatus(player.unit);
        if rc=='ready' then
            player.isReady = 1;
        elseif rc=='notready' then
            player.isReady = 0;
        elseif rc=='waiting' then
            player.isReady = nil;
        end
    end
	StatusDirty = GetTime()
end

local OZ_Events = {
	["RAID_ROSTER_UPDATE"] = OZ_EventRoster,
	["PARTY_MEMBERS_CHANGED"] = OZ_EventRoster,
	["RAID_TARGET_UPDATE"] = OZ_EventStatus,
	["PARTY_MEMBER_DISABLE"] = OZ_EventRoster,
	["PARTY_MEMBER_ENABLE"] = OZ_EventRoster,
	["UNIT_AURA"] = OZ_EventStatus,
	["UNIT_HEALTH"] = OZ_EventStatus,
	["UNIT_MANA"] = OZ_EventStatus,
	["UNIT_MAXHEALTH"] = OZ_EventStatus,
	["UNIT_MAXMANA"] = OZ_EventStatus,
    ["READY_CHECK"] = OZ_readyCheck,
    ["READY_CHECK_CONFIRM"] = OZ_readyCheck,
--    ["READY_CHECK_FINISHED"] = OZ_readyCheck,    
	["VARIABLES_LOADED"] = OzRaidLoadSavedVariables,
	["PLAYER_TARGET_CHANGED"] = OZ_EventTarget,
}

function OZ_SetupEvents()
	local key,val
	for key,value in pairs(OZ_Events) do
		this:RegisterEvent(key)
	end
end

function OzRaidFormEvent(arg1)
	local f = OZ_Events[event]
	if f then
		f()
    end
end


OZ_CurrentTime = 0;
OZ_ReadyCheckTimer = 0;
OZ_ReadyCheckActive = nil;
OZ_ReadyCheckStart = nil;


OZ_Initialised = nil
OZ_UpdateTimer = 0
OZ_UpdatePause = 0.1
local roster = 0
local lastUpdate = 0

local hasOptions

local nextWindow = 1

function OzRaid_OnUpdate()
	local i

-- NEW
-- Check for tooltips...
-- OZ_CurrentTooltipBar = OZ_Bar bar for current tooltip
-- OZ_CurrentTooltipFrame = current UI frame for the BAR
-- OZ_CurrentTooltipCurrent = current UI frame of the BUFF

if OZ_CurrentTooltipBar and MouseIsOver(OZ_CurrentTooltipFrame) then
	-- Showing a tooltip.
	if OZ_CurrentTooltipCurrent then
		-- We are showing a buff tooltip
		if not MouseIsOver(OZ_CurrentTooltipCurrent) then
			-- Change to bar
			OZ_ToolTip(OZ_CurrentTooltipFrame)
		end
	else
		-- We are over the bar, just check our buffs...
		for i=1,OZ_MAX_BUFFS do
			if MouseIsOver(OZ_CurrentTooltipBar.buff[i]) then
				OZ_BuffTooltip(OZ_CurrentTooltipBar.buff[i]);
				OZ_CurrentTooltipCurrent = OZ_CurrentTooltipBar.buff[i];
				break;
			end
		end
	end
end


	if(OZ_Initialised) then
		_CurrentTime = GetTime()
		local t = _CurrentTime - OZ_UpdateTimer
		if t>0 then
			if t > OZ_UpdatePause then
				OZ_UpdatePause = OZ_UpdatePause * 2
				if OZ_UpdatePause > 0.8 then
					OZ_UpdatePause = 0.8
				end
			elseif t > 0.1 then
				OZ_UpdatePause = OZ_UpdatePause * 0.5
			else
				OZ_UpdatePause = 0.1
			end
			if hasOptions then
				if(OzRaidOptions:IsVisible())then
					OZ_OptionsSetConfigFromOptions()
					_CurrentTime = GetTime()
				end
			end
			OZ_UpdateTimer = (_CurrentTime + OZ_UpdatePause)
            OZ_CurrentTime = _CurrentTime

            -- Check for a pending readyCheck
            if GetReadyCheckTimeLeft()>0 then
                OZ_ReadyCheckTimer = _CurrentTime;
                OZ_ReadyCheckActive = 1;
            elseif OZ_ReadyCheckActive == 1 then
                -- Readycheck timer is over...
                OZ_ReadyCheckActive = 2               
            end
            
			if RosterDirty>lastUpdate or _CurrentTime>RosterDirty+10 then
				OZ_UpdateRoster()
				RosterDirty = lastUpdate
				StatusDirty = _CurrentTime
			end
			t = GetTime() - _CurrentTime
			if t>0.05 then
				print("OzRaid - 延迟检测 (1)")
				return
			end

			roster = roster + 1
			if(roster > 50)then
				roster = 0
				if not InCombatLockdown() then

--					if(OZ_Config[1].hideparty)then
--						HidePartyFrame()
--					else
--						ShowPartyFrame()
--					end
if not OZ_RaidRoster.solo then
	if OZ_RaidRoster.inParty then
		if OZ_Config.pFramesParty == 1 then
			ShowPartyFrame()
		elseif OZ_Config.pFramesParty == 2 then
			HidePartyFrame()
		end
	else
		if OZ_Config.pFramesRaid == 1 then
			ShowPartyFrame()
		elseif OZ_Config.pFramesRaid == 2 then
			HidePartyFrame()
		end
	end
end

				end
			end


			-- Now update windows
			-- Use nextWindow as the iterator, so if we early out
			-- we can pickup where we left off.
			if nextWindow > OZ_NWINDOWS then
				nextWindow = 1
			end
			local stop = nextWindow - 1
			if stop<1 then
				stop = OZ_NWINDOWS
			end
			local nProcessed = 0
			if OZ_NWINDOWS>0 then
				while nextWindow~=stop or nProcessed<1 do
					nProcessed = nProcessed + 1
					t = GetTime() - _CurrentTime
					if t>0.05 then
						-- LAAAAGGGG
--						print("OzRaid - 延迟检测 (2)")
						return
					end
					OzRaid_Update(nextWindow)
					nextWindow = nextWindow + 1
					if nextWindow>OZ_NWINDOWS then
						nextWindow = 1
					end
				end
			end
			lastUpdate = _CurrentTime
			_CurrentTime = _CurrentTime + 0.0001
 		end
	end
end

function OzRaid_Update(n)
	local config = OZ_Config[n]
	if(config.active)then
		if(not OZ_Windows[n])then
			OZ_InitWindow(n)
		end

		local frame = OZ_Windows[n].frame
		if(frame.tNext < _CurrentTime)then
			-- Check for hide on solo
			if( ((config.hideSolo)and(OZ_RaidRoster.solo)) or
				((config.hideParty)and(OZ_RaidRoster.inParty)) )then
				if( frame:IsVisible() )then
						frame:Hide()
				end
			else
				if(not frame.moving)then
					-- Check something is dirty (or we are a target window)
					if StatusDirty > frame.lastUpdate or
                        RosterDirty > frame.lastUpdate or
						OZ_InputFunctions[OZ_Config[n].input].always then
                        
                        if OZ_InputFunctions[OZ_Config[n].input].always then
                            OZ_InputFunctions[OZ_Config[n].input].always = OZ_InputFunctions[OZ_Config[n].input].always + 1;
                            if(OZ_InputFunctions[OZ_Config[n].input].always >= 0)then
                                OZ_InputFunctions[OZ_Config[n].input].always = nil;
                            end
                        end
--6print("UPDATE "..n.." @ "..GetTime());
						OZ_ProcessBars(n)
						OZ_SetBars(n)
						OZ_CheckVisibility(n)
						frame.lastUpdate = _CurrentTime
					end
				end
			end
			frame.tNext = _CurrentTime + config.refresh
		end
	end
end

-- This function ensure health/mana is updated as frequently as the fastest window
-- but no faster than 5 times a second
local LastUnitUpdate = 0
function OzRaid_UpdateUnitData()
	local i
	if( _CurrentTime > LastUnitUpdate)then
		for i=1,OZ_RaidRoster.nMembers do
			OZ_SetExtraMemberData(i)
		end
		LastUnitUpdate = _CurrentTime
	end
end

local LastTargetUpdate = 0
function OzRaid_UpdateTargetData()
	local _CurrentTime = GetTime()
	local i
	if( _CurrentTime > LastTargetUpdate + 0.2)then
		OZ_UpdateTargets()
		LastTargetUpdate = _CurrentTime
	end
end


function OZ_CheckVisibility(n)
	local window = OZ_Windows[n]
	local config = OZ_Config[n]
	if( ((config.hideSolo)and(OZ_RaidRoster.solo)) or
		((config.hideParty)and(OZ_RaidRoster.inParty)) )then
		if( window.frame:IsVisible() )then
				window.frame:Hide()
		end
		return
	end

	if( window.frame:IsVisible() )then
		if( (not config.active) or
			( config.hideEmpty and (OZ_Bars[n].nBars == 0)) )then
			window.frame:Hide()
		end
	else
		if( (config.active) and
			((not config.hideEmpty) or (OZ_Bars[n].nBars > 0)) )then
			window.frame:Show()
		end
	end
end

function OZ_Button_OnLeave()
 --TODO: clear tooltip
end

function OZ_Button_OnEnter(name)
 --TODO: Set tooltip
end

function OZ_Button_Close(frame)
	local id = frame:GetParent():GetParent():GetID()
	OZ_Config[id].active = nil
	OZ_Windows[id].frame:Hide()
	if hasOptions then
		if(id == OZ_OptionsCurrentWindow)then
			OZ_OptionsSetOptionsFromConfig(id)
		end
	end
end

function OZ_LoadOptions()
	if not hasOptions then
		local loaded,reason = LoadAddOn("OzOptions")
		if not loaded then
			DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF".."OzRaid:打开选项失败. 原因 = "..reason)
		else
			OZ_OptionsInit(1)
		end
		hasOptions = true
	end
end

function OZ_Button_Options(frame)
	OZ_LoadOptions()

	-- Need to get the frame name...
	local id = frame:GetParent():GetParent():GetID()

	OZ_OptionsSetOptionsFromConfig(id)
	-- Bung a hide in - this refreshes the dropdowns ;)
	OzRaidOptions:Hide()
	OzRaidOptions:Show()
end

function OZ_Button_BuffClick(frame)
-- TODO: Handle the click
end


function DumpHierarchy(src, q, depth)
	local i
	if (src and (q>0)) then
		local a="";
		if(depth) then
			for i=0,depth do
				a = a.."   "
			end
		else
			depth = 0
		end
		if (src:GetName()) then
			a = a..src:GetName();
		end
		if (src:GetObjectType()) then
			local x,y,w,h;
			x = src:GetLeft();
			if (not x) then
				x=0;
			end
			y = src:GetTop();
			if (not y) then
				y=0;
			end
			w = src:GetWidth();
			if (not y) then
				y=0;
			end
			h = src:GetHeight();
			if (not y) then
				y=0;
			end

			a = a..format(":  x=%.2f, y=%.2f, w=%.2f, h=%.2f",x,y,w,h);
		end

		DEFAULT_CHAT_FRAME:AddMessage(a);

		if (src:IsObjectType("Frame")) then
			local kids = { src:GetChildren() };
			for _,child in ipairs(kids) do
				DumpHierarchy(child, q-1, depth+1);
			end
			local kids2 = { src:GetRegions() };
			for _,child in ipairs(kids2) do
				DumpHierarchy(child, q-1, depth+1);
			end
		end

	end
end

function OZ_ToggleWindow( n )
	local window = "OzRaid_Frame"..n
	local wObj = getglobal(window)
	if(wObj)then
		local i = wObj:GetID()
		if(OZ_Config[i].active)then
			wObj:Hide()
			OZ_Config[i].active = nil
		else
			wObj:Show()
			OZ_Config[i].active = 1
		end
	else
		OZ_LoadOptions()

		OZ_OptionsSetOptionsFromConfig(1)
		OzRaidOptions:Show()
	end
end

function OzTarget( window, bar )
	if(not window)then
		DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF".."OzRaid: 错误, 无窗口ID!\n用法: /oztarget <窗口ID><状态条编号>");
		return
	end
	if(not bar)then
		DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF".."OzRaid: 错误, 无状态条ID!\n 用法: /oztarget <窗口ID><状态条编号>");
		return
	end
	local wName = "OzRaid_Frame"..window
	local wObj = getglobal(wName)
	local i
	if(not wObj)then
		-- Hmm, try finding the window by name
		for i=1,OZ_NWINDOWS do
			if( window == OZ_Config[i].text )then
				wObj = OZ_Windows[i].frame
				wName = wObj:GetName()
				break
			end
		end
		if(not wObj)then
			DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF".."OzRaid: 错误, 找不到窗口 ID/名称!");
			return
		end
	end

	local barName = wName.."TableRow"..bar.."BarFrame"
	local barObj = getglobal(barName)
	if(not barObj)then
		DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF".."OzRaid: 错误, 找不到状态条ID!");
		return
	end
	if(barObj.unit)then
		TargetUnit(barObj.unit)
		return true
	else
		DEFAULT_CHAT_FRAME:AddMessage("|c0033CCFF".."OzRaid: 错误,状态上无单位信息!");
	end
end
function OZ_ClickBar(unit,button)
	if(unit)then
		-- Allow a custom click function 'OzRaidCustomClick'
		if OzRaidCustomClick and OzRaidCustomClick(button, unit) then
		  return
		end

		-- 'CastParty'
		if( CastParty_OnClickByUnit and CastPartyConfig ) then
			local action_key = '';
			if IsAltKeyDown() then
				action_key = action_key .. 'Alt';
			end
			if IsControlKeyDown() then
				action_key = action_key .. 'Ctrl';
			end
			if IsShiftKeyDown() then
				action_key = action_key .. 'Shift';
			end
			if action_key == '' then
				action_key = 'None';
			end

			local action = CastPartyConfig.key_bindings[button][action_key];
			if (action ~= 'CastParty_WoWDefaultClick' and action ~= 'CastParty_PartyDropDown' and action ~= CASTPARTY_KEYBINDINGS_NONE) then
				CastParty_OnClickByUnit(button, unit);
				return;
			end
		end

		-- 'JustClick' 
		if( JC_CatchKeyBinding ) then
			if ( JC_CatchKeyBinding(button, unit) ) then
				return;
			end
		end
		-- 'ClickHeal'
		if( CH_UnitClicked )then
			if ( CH_UnitClicked(unit, button) ) then
				return;
			end
		end

		if ( SpellIsTargeting() ) then
			if ( not SpellCanTargetUnit(unit) ) then
				SetCursor("CAST_ERROR_CURSOR");
			else
				if ( button == "LeftButton" ) then
					SpellTargetUnit(unit);
				elseif ( button == "RightButton" ) then
					SpellStopTargeting();
				end
			end
			return;
		end

		if ( CursorHasItem() ) then
			if ( button == "LeftButton" ) then
				if ( UnitIsUnit(unit, "player") ) then
					AutoEquipCursorItem();
				else
					DropItemOnUnit(unit);
				end
			else
				PutItemInBackpack();
			end
			return;
		end

		TargetUnit(unit);
		if( button == "RightButton" )then
			ToggleDropDownMenu(1, nil, TargetFrameDropDown, this:GetName(), 0, 10);
		end
	end
end


SLASH_OZRAID1 = "/ozraid";
SLASH_OZRAID2 = "/oz"; -- A shortcut or alias

SlashCmdList["OZRAID"] = OZ_ToggleWindow;

BINDING_HEADER_OZRAID	= "OzRaid 快捷键"
BINDING_NAME_WINDOW1	= "开启/关闭 OzRaid 1"
BINDING_NAME_WINDOW2	= "开启/关闭 OzRaid 2"
BINDING_NAME_WINDOW3	= "开启/关闭 OzRaid 3"
BINDING_NAME_WINDOW4	= "开启/关闭 OzRaid 4"
BINDING_NAME_WINDOW5	= "开启/关闭 OzRaid 5"
BINDING_NAME_WINDOW6	= "开启/关闭 OzRaid 6"
BINDING_NAME_WINDOW7	= "开启/关闭 OzRaid 7"
BINDING_NAME_WINDOW8	= "开启/关闭 OzRaid 8"

----------------------------------------------------
-- Minimap Icon
----------------------------------------------------
function OZ_SetMinimapPos()
	if(OZ_Config.minimapShow)then
		OzRaid_IconFrame:SetPoint("TOPLEFT", "Minimap", "TOPLEFT", 52 - OZ_Config.minimapDist * cos(OZ_Config.minimapAngle), OZ_Config.minimapDist * sin(OZ_Config.minimapAngle) - 52)
		OzRaid_IconFrame:Show()
	else
		OzRaid_IconFrame:Hide()
	end
end

function OzRaid_IconFrameOnEnter()
end

function OzRaid_IconFrameOnClick()
	OZ_LoadOptions(1)
	OZ_OptionsSetOptionsFromConfig(1)
	OzRaidOptions:Show()
end

UnitPopupButtons["OZRAID_TEST"] = { text = "OzRaid test", dist = 0 };

